﻿namespace TestTool.GUI.Controllers
{
    using System;
    using System.Globalization;
    using System.Threading;
    using TestTool.GUI.Data;
    using TestTool.GUI.Enums;
    using TestTool.GUI.Utils;
    using TestTool.GUI.Views;
    using TestTool.Proxies.Onvif;

    internal class DeviceManagementController : Controller<IDeviceManagementView>
    {
        private ManagementServiceProvider _client;
        private bool _idle;

        public DeviceManagementController(IDeviceManagementView view) : base(view)
        {
            this._idle = true;
        }

        private void _client_ExceptionThrown(string stage, Exception exc)
        {
            string message;
            this._idle = true;
            Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
            if (!string.IsNullOrEmpty(stage))
            {
                message = string.Format("{0}{1}{2}", stage, Environment.NewLine, exc.Message);
            }
            else
            {
                message = exc.Message;
            }
            base.View.DisplayLog(message.Replace("\n", Environment.NewLine));
        }

        private void _client_OnDeviceInformationReceived(string manufacturer, string model, string firmwareVersion, string serial, string hardwareId)
        {
            base.View.DisplayDeviceInformation(manufacturer, model, firmwareVersion, serial, hardwareId);
        }

        private void _client_OperationCompleted()
        {
            this._idle = true;
            base.ReportOperationCompleted();
        }

        private void _client_OperationStarted()
        {
            base.ReportOperationStarted();
        }

        private void _client_ResponseReceived(string response)
        {
            base.View.DisplayLog(response);
        }

        public bool DeviceNotEmpty()
        {
            DiscoveredDevices discoveredDevices = ContextController.GetDiscoveredDevices();
            return ((discoveredDevices != null) && !string.IsNullOrEmpty(discoveredDevices.ServiceAddress));
        }

        public void GetCapabilities()
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.GetCapabilities(new CapabilityCategory[1]);
            }
        }

        public void GetDeviceInformation()
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.GetDeviceInformation();
            }
        }

        public void GetHostname()
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.GetHostname();
            }
        }

        public void GetNetworkInterfaces()
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.GetInterfaces();
            }
        }

        public void GetScopes()
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.GetScopes();
            }
        }

        public void GetServices()
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.GetServices();
            }
        }

        public void HardReset()
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.HardReset();
            }
        }

        private bool InitializeClient()
        {
            string uriString = string.Empty;
            DiscoveredDevices discoveredDevices = ContextController.GetDiscoveredDevices();
            if (discoveredDevices.Current != null)
            {
                uriString = discoveredDevices.ServiceAddress;
            }
            try
            {
                new Uri(uriString);
            }
            catch (Exception)
            {
                base.View.ShowError("Device service address is invalid!");
                return false;
            }
            try
            {
                DeviceEnvironment deviceEnvironment = ContextController.GetDeviceEnvironment();
                this._client = new ManagementServiceProvider(uriString, deviceEnvironment.Timeouts.Message);
                this._client.ExceptionThrown += new Action<string, Exception>(this._client_ExceptionThrown);
                this._client.OnDeviceInformationReceived += new ManagementServiceProvider.DeviceInformationReceived(this._client_OnDeviceInformationReceived);
                this._client.OperationCompleted += new Action(this._client_OperationCompleted);
                this._client.OperationStarted += new Action(this._client_OperationStarted);
                this._client.ResponseReceived += new Action<string>(this._client_ResponseReceived);
                this._client.Security = ContextController.GetDebugInfo().Security;
                return true;
            }
            catch (Exception exception)
            {
                base.View.ShowError(string.Format("Error occurred: {0}", exception.Message));
                return false;
            }
        }

        public void Reboot()
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.Reboot();
            }
        }

        public void SetGateway(string gateway)
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.SetGateway(gateway);
            }
        }

        public void SetIPAddress(string token, string ipAddress, int prefixLength)
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.SetIPAddress(token, ipAddress, prefixLength);
            }
        }

        public override void Stop()
        {
            this._client.Stop();
        }

        public void SyncTime()
        {
            if (this.InitializeClient())
            {
                this._idle = false;
                this._client.SyncTime();
            }
        }

        public override void UpdateView()
        {
            DiscoveredDevices discoveredDevices = ContextController.GetDiscoveredDevices();
            if (discoveredDevices != null)
            {
                base.View.DeviceManagementUrl = discoveredDevices.ServiceAddress;
                base.View.IP = (discoveredDevices.DeviceAddress != null) ? discoveredDevices.DeviceAddress.ToString() : string.Empty;
                if ((this._client != null) && (this._client.Address != discoveredDevices.ServiceAddress))
                {
                    base.View.Clear();
                }
            }
            else
            {
                base.View.DeviceManagementUrl = string.Empty;
                base.View.IP = string.Empty;
                base.View.Clear();
            }
            DeviceEnvironment deviceEnvironment = ContextController.GetDeviceEnvironment();
            if (this._client != null)
            {
                this._client.Timeout = deviceEnvironment.Timeouts.Message;
            }
        }

        public override void UpdateViewFunctions()
        {
            base.View.EnableFunctions((this.DeviceNotEmpty() && this._idle) && (base.CurrentState == TestTool.GUI.Enums.ApplicationState.Idle));
        }

        public override bool RequestPending
        {
            get
            {
                return !this._idle;
            }
        }
    }
}

